(function($) {

    var _startSockJS = function(consoleServer, sessionKey, consoleID, guid) {
        $('#id_connecting_to_server_indicator_text').text(
            "Starting encrypted connection to "
            + consoleServer +
            " on port 443"
        );
        $('#id_connecting_to_server_indicator').show();
        if (Anywhere.sockjs) {
            Anywhere.sockjs.onclose = function () {};
            Anywhere.sockjs.close();
        }
        Anywhere.sockjs = new SockJS('https://' + consoleServer + '/sj');
        Anywhere.sockjs.onopen = function(data) {
            Anywhere.reconnect_wait = 1000;
            Anywhere.siab.reset();
            Anywhere.sockjs.send('session_key=' + sessionKey + '&console_id=' + consoleID + '&guid=' + guid);
            $('#id_connecting_to_server_indicator').hide();
            Anywhere.sockjs.send('width=' + Anywhere.siab.terminalWidth + '&height=' + Anywhere.siab.terminalHeight);
        };
        Anywhere.sockjs.onmessage = _incomingMessageHandler;
        Anywhere.sockjs.onerror = Anywhere.reconnect;
        Anywhere.sockjs.onclose = Anywhere.reconnect;

        Anywhere.incoming = [];
    };

    var _incomingMessageHandler = function(data) {
        Anywhere.incoming.push(data.data);
        setTimeout(
            function() {
                nextData = Anywhere.incoming.shift();
                var out = '';
                for (var i=0; i < nextData.length; i+=2) {
                    var byte = parseInt(nextData.slice(i, i + 2), 16);
                    out += String.fromCharCode(byte);
                }
                Anywhere.siab.vt100(out);
            },
            0
        );
    };

    var _keyPressHandler = function(chars) {
        var encoded = '';
        for (var i=0; i < chars.length; i++) {
            thisChar = chars.charCodeAt(i).toString(16);
            while (thisChar.length < 4) {
                thisChar = '0' + thisChar;
            }
            thisChar = thisChar.slice(-2) + thisChar.slice(0, 2);
            encoded = encoded + thisChar;
        }
        Anywhere.sockjs.send(encoded);
    };

    var lastWidth;
    var lastHeight;
    var _resizeHandler = function(width, height) {
        if (width != lastWidth || height != lastHeight) {
            Anywhere.sockjs.send('width=' + width + '&height=' + height);
            lastWidth = width;
            lastHeight = height;
        }
    };

    var _showContextMenu = function() {};

    var _startShell = function() {
         var siab = new SIAB.Console();
         siab.visualBell = true;
         siab.showContextMenu = Anywhere._showContextMenu;
         siab.keysPressed = Anywhere._keyPressHandler;
         siab.resized = Anywhere._resizeHandler;
         Anywhere.siab = siab;
    };

    var LoadConsole = function(consoleServer, sessionKey, consoleId, guid) {
        Anywhere._startShell();
        Anywhere.reconnect = function () {
            setTimeout(
                function() {Anywhere._startSockJS(consoleServer, sessionKey, consoleId, guid);},
                Anywhere.reconnect_wait
            );
            Anywhere.reconnect_wait *= 2;
            if (Anywhere.reconnect_wait > 16000) {
                Anywhere.reconnect_wait = 16000;
            }
        };
        Anywhere._startSockJS(consoleServer, sessionKey, consoleId, guid);
    };


    $.extend(true, window, {
        'Anywhere': {
            'connected': false,
            'LoadConsole': LoadConsole,
            'reconnect': null,
            'reconnect_wait': 1000,
            'siab': null,
            'sockjs': null,
            '_incomingMessageHandler': _incomingMessageHandler,
            '_keyPressHandler': _keyPressHandler,
            '_resizeHandler': _resizeHandler,
            '_showContextMenu': _showContextMenu,
            '_startShell': _startShell,
            '_startSockJS': _startSockJS
        }
    });

})(jQuery);
